package com.sinodata.bsm.center.web.action.performance;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import com.sinodata.bsm.center.bean.PropValueBean;
import com.sinodata.bsm.center.bean.RelationHelper;
import com.sinodata.bsm.center.bean.ResBean;
import com.sinodata.bsm.center.bean.ResTypeBean;
import com.sinodata.bsm.center.cache.CollectFieldCache;
import com.sinodata.bsm.center.cache.PropertyCache;
import com.sinodata.bsm.center.cache.PropertyDisplayCache;
import com.sinodata.bsm.center.cache.PropertyValueCache;
import com.sinodata.bsm.center.service.performance.PropValueService;
import com.sinodata.bsm.center.service.performance.RealTimeService;
import com.sinodata.bsm.center.service.resource.CollectTaskService;
import com.sinodata.bsm.center.service.resource.PropertyService;
import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.center.util.web.Struts2Utils;
import com.sinodata.bsm.center.web.action.BaseAction;
import com.sinodata.bsm.common.constants.DataTypeConstants;
import com.sinodata.bsm.common.utils.DateUtil;
import com.sinodata.bsm.common.vo.CollectField;
import com.sinodata.bsm.common.vo.CollectTask;
import com.sinodata.bsm.common.vo.Property;
import com.sinodata.bsm.common.vo.PropertyDisplay;
import com.sinodata.bsm.common.vo.PropertyValue;
import com.sinodata.bsm.common.vo.Res;

import edu.emory.mathcs.backport.java.util.Arrays;

public class PropValueAction extends BaseAction {
    /**
     * 
     */
    @Autowired
    private PropValueService propService;
    @Autowired
    private PropertyService propertyService;

    @Autowired
    private CollectTaskService collectTaskService;

    @Autowired
    private CollectFieldCache collectFieldCache;

    @Autowired
    private PropertyDisplayCache propertyDisplayCache;

    private static final long serialVersionUID = 1L;
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String delete() throws Exception {
        return null;
    }

    @Override
    public String input() throws Exception {
        return null;
    }

    @Override
    public String execute() throws Exception {
        request.setAttribute("resId", id);
        return SUCCESS;
    }

    @Override
    public String list() throws Exception {
        RealTimeService realTimeService = SpringContextHolder.getBean(RealTimeService.class);
        SimpleDateFormat ff = new SimpleDateFormat("HH:mm:ss yyyy-MM-dd");

        realTimeService.collectPropertyValues(new Long[] { this.id });

        Res res = ResBean.get(this.id).res();
        Long resTypeId = res.getResTypeId();
        List<Property> propList = ResTypeBean.get(resTypeId).properties();
        // 用户自定义指标
        List<Property> definedProperty = propertyService.findPropertyByResId(this.id);
        if (definedProperty != null) {
            for (Property p : definedProperty) {
                CollectField field = collectFieldCache.getByPropId(p.getId());
                if (field != null && field.getFieldName() != null) {
                    propList.add(p);
                }
            }
        }
        Collections.sort(propList, new Comparator<Property>() {
            @Override
            public int compare(Property p0, Property p1) {
                return p0.getDisplay().intValue() - p1.getDisplay().intValue();

            }
        });
        JSONArray array = new JSONArray();
        PropertyValueCache cache = SpringContextHolder.getBean(PropertyValueCache.class);

        List<CollectTask> resTaskList = collectTaskService.findByResId(this.id);// 采集器实例
        List<CollectTask> taskList = new ArrayList<CollectTask>(); // 显示的结果
        List<CollectTask> typelist = collectTaskService.findByResTypeId(res.getResTypeId());
        if (resTaskList != null) {
            taskList.addAll(resTaskList);
            for (int i = 0; typelist != null && i < typelist.size(); i++) {
                CollectTask task = typelist.get(i);
                boolean hasConf = false;
                for (CollectTask task2 : resTaskList) {
                    if (task2.getResTypeTaskId() != null && task.getId().longValue() == task2.getResTypeTaskId()) {
                        hasConf = true;
                    }
                }
                if (!hasConf) {
                    taskList.add(task);
                }
            }
        } else if (typelist != null) {
            taskList.addAll(typelist);
        }

        //批量采集的资源的采集规则是定义在其父资源上的，所有要将父资源的采集规则添加到taskList中
        taskList.addAll(collectTaskService.findFatherTaskByResId(this.id));

        CollectFieldCache collectFieldCache = SpringContextHolder.getBean(CollectFieldCache.class);
        Set<Long> propSet = new HashSet<Long>();
        for (CollectTask task : taskList) {
            List<CollectField> fields = collectFieldCache.get(task.getId());
            if (fields != null) {
                for (CollectField field : fields) {
                    propSet.add(field.getProp());
                }
            }
        }

        for (int i = 0; i < propList.size(); i++) {
            Property prop = propList.get(i);
            if (prop.getDataTypeId().intValue() == DataTypeConstants.DATA_TYPE_OBJECT && prop.getFormat() != null) {
                continue;
            }
            JSONObject obj = new JSONObject();
            String n = prop.getDataUnit() == null ? prop.getName() : prop.getName() + "(" + prop.getDataUnit() + ")";
            //自定义sql记录查询、自定义脚本监控 指标名称将显示别名
            if (resTypeId.longValue() == 1205040600000L || resTypeId.longValue() == 1205040500000L) {
                PropertyDisplay anotherEntity = propertyDisplayCache.getExample(res.getId(), resTypeId, prop.getId());
                n = anotherEntity == null ? n : anotherEntity.getDisplayName();
            }

            obj.element("propname", n);
            PropValueBean bean = cache.getValueBean(id.longValue(), prop.getId().longValue());
            obj.element("propId", prop.getId().longValue());
            obj.element("dataType", prop.getDataTypeId().longValue());
            if (bean != null) {

                if (prop.getDataTypeId().intValue() == DataTypeConstants.DATA_TYPE_BOOLEAN) {
                    if (DataTypeConstants.BOOLEAN_VALUE_TRUE.equals(bean.getValue())) {
                        obj.element("propvalue", DataTypeConstants.BOOLEAN_VALUE_TRUE_DISPLAY);
                    } else if (DataTypeConstants.BOOLEAN_VALUE_FALSE.equals(bean.getValue())) {
                        obj.element("propvalue", DataTypeConstants.BOOLEAN_VALUE_FALSE_DISPLAY);
                    } else {
                        obj.element("propvalue", bean.getValue());
                    }
                } else {
                    String val = bean.getValue();

                    if (prop.getDataTypeId().intValue() == DataTypeConstants.DATA_TYPE_DATE) {
                        SimpleDateFormat f = new SimpleDateFormat(prop.getFormat());
                        obj.element("propvalue", prop.getFormat() == null ? DateUtil.getDateTime(Long.parseLong(val)) : f.format(new Date(Long.parseLong(val))));
                    } else {
                        obj.element("propvalue", val);
                    }
                }
                obj.element("collectTime", ff.format(bean.getTime()));
                array.add(obj);
            } else {
                if (prop.getResId() != null || propSet.contains(prop.getId())) {
                    obj.element("propvalue", "-");
                    obj.element("collectTime", "-");
                    array.add(obj);
                }
            }
        }
        JSONObject json = new JSONObject();
        json.element("iTotalRecords", propList.size());
        json.element("iTotalDisplayRecords", propList.size());
        json.element("aaData", array);
        Struts2Utils.renderText(json.toString());
        return null;
    }

    /**
     * 显示子资源的列表
     * @return
     */
    @SuppressWarnings("unchecked")
    public String showResList() {
        JSONObject json = new JSONObject();
        try {
            ResBean rbean = ResBean.get(this.id);
            if (rbean == null) {
                return null;
            }
            ResTypeBean bean = ResTypeBean.get(rbean.res().getResTypeId());
            if (bean == null) {
                return null;
            }

            List<CollectTask> resTaskList = collectTaskService.findByResId(rbean.res().getId());//采集器实例
            List<CollectTask> taskList = new ArrayList<CollectTask>(); //显示的结果
            List<CollectTask> typelist = collectTaskService.findByResTypeId(bean.resType().getId());
            if (resTaskList != null) {
                taskList.addAll(resTaskList);
                for (int i = 0; typelist != null && i < typelist.size(); i++) {
                    CollectTask task = typelist.get(i);
                    boolean hasConf = false;
                    for (CollectTask task2 : resTaskList) {
                        if (task2.getResTypeTaskId() != null && task.getId().longValue() == task2.getResTypeTaskId()) {
                            hasConf = true;
                        }
                    }
                    if (!hasConf) {
                        taskList.add(task);
                    }
                }
            } else if (typelist != null) {
                taskList.addAll(typelist);
            }

            //批量采集的资源的采集规则是定义在其父资源上的，所有要将父资源的采集规则添加到taskList中
            taskList.addAll(collectTaskService.findFatherTaskByResId(this.id));

            CollectFieldCache collectFieldCache = SpringContextHolder.getBean(CollectFieldCache.class);
            Set<Long> propSet = new HashSet<Long>();
            for (CollectTask task : taskList) {
                List<CollectField> fields = collectFieldCache.get(task.getId());
                if (fields != null) {
                    for (CollectField field : fields) {
                        propSet.add(field.getProp());
                    }
                }
            }

            List<Property> properties = bean.properties();
            List<Property> definedProperty = propertyService.findPropertyByResId(this.id);
            if (definedProperty != null) {
                properties.addAll(definedProperty);
            }

            int validSize = 0;
            for (Property p : properties) {
                if (propSet.contains(p.getId())) {
                    validSize++;
                } else {
                    continue;
                }
            }

            JSONArray array = new JSONArray();
            List<ResBean> children = RelationHelper.children(this.id);
            Collections.sort(children, new ResHealthSort());

            for (int i = 0; i < children.size(); i++) {
                ResBean child = children.get(i);
                JSONArray ay = new JSONArray();
                ay.add(child.res().getName());
                ay.add("<span class='health' id=child" + i + " value=" + child.res().getHealthDegree() + "></span>");
                ay.add(child.type().resType().getName());
                ay.add(child.res().getIp());
                ay.add(child.res().getDesc() == null ? "&nbsp;" : child.res().getDesc());
                array.add(ay);
            }
            json.element("resSize", children.size());
            json.element("size", validSize);
            json.element("data", array);
        } catch (Exception e) {
            json.element("size", "0");
        }
        Struts2Utils.renderText(json.toString());
        return null;
    }

    @SuppressWarnings("unchecked")
    public String showSubTypeRes() {
        Long resTypeId = Long.parseLong(Struts2Utils.getParameter("id"));
        Long parentId = Long.parseLong(Struts2Utils.getParameter("pId"));
        ResBean[] resArray = ResBean.get(parentId).childrenByType(resTypeId);
        List<ResBean> children = new ArrayList<ResBean>(Arrays.asList(resArray));
        Collections.sort(children, new ResHealthSort());

        JSONObject json = new JSONObject();
        JSONArray array = new JSONArray();
        for (int i = 0; i < children.size(); i++) {
            ResBean child = children.get(i);
            JSONArray ay = new JSONArray();
            ay.add(child.res().getName());
            ay.add("<span class='health' id=child" + i + " value=" + child.res().getHealthDegree() + "></span>");
            ay.add(child.res().getIp());
            ay.add(child.res().getDesc() == null ? "&nbsp;" : child.res().getDesc());
            array.add(ay);
        }
        json.element("data", array);
        Struts2Utils.renderText(json.toString());
        return null;
    }

    // 初始化tooltip
    public String tooltip() throws Exception {
        String propId = request.getParameter("propId");
        PropertyCache cache = SpringContextHolder.getBean(PropertyCache.class);
        Property prop = cache.get(Long.parseLong(propId));
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.HOUR_OF_DAY, -1);
        SimpleDateFormat ff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String endDate = ff.format(cal.getTime());
        cal.add(Calendar.DATE, -1);
        String beginDate = ff.format(cal.getTime());
        List<PropertyValue> list = propService.getPropValues(this.id, new int[] { prop.getStore() }, beginDate, endDate, "1");
        request.setAttribute("valueList", list);
        PropertyValueCache currentcache = SpringContextHolder.getBean(PropertyValueCache.class);
        String current = currentcache.getValue(this.id, prop.getId());
        request.setAttribute("resId", this.id.toString());
        request.setAttribute("currentval", current);
        request.setAttribute("propId", propId);
        return "tooltip";
    }

    // 由javascript动态调用
    public String tooltip2() throws Exception {
        String propId = request.getParameter("propId");
        String recType = request.getParameter("type");
        if (recType == null)
            recType = "1";
        PropertyCache cache = SpringContextHolder.getBean(PropertyCache.class);
        Property prop = cache.get(Long.parseLong(propId));
        Calendar cal = Calendar.getInstance();
        String endDate = null;
        String beginDate = null;
        SimpleDateFormat ff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (recType.equals("1")) {
            cal.add(Calendar.HOUR_OF_DAY, -1);
            endDate = ff.format(cal.getTime());
            cal.add(Calendar.DATE, -1);
            beginDate = ff.format(cal.getTime());
        } else {
            cal.add(Calendar.DATE, -1);
            endDate = ff.format(cal.getTime());
            cal.add(Calendar.DATE, -12);
            beginDate = ff.format(cal.getTime());
        }
        List<PropertyValue> list = propService.getPropValues(this.id, new int[] { prop.getStore() }, beginDate, endDate, recType);
        PropertyValueCache currentcache = SpringContextHolder.getBean(PropertyValueCache.class);
        String current = currentcache.getValue(this.id, prop.getId());
        JSONObject json = new JSONObject();
        json.element("propValues", list);
        json.element("currentval", current);
        json.element("propId", propId);
        Struts2Utils.renderText(json.toString());
        return null;
    }

    /**
     * 构建资源 实时性能 指标数据dataunit为4(对象型)的datatables数据
     * 
     * @return
     */
    public String initDatatables() {
        PropertyValueCache cache = SpringContextHolder.getBean(PropertyValueCache.class);
        Long resId = Long.parseLong(Struts2Utils.getParameter("resId"));
        Res res = ResBean.get(resId).res();
        List<Property> propList = ResTypeBean.get(res.getResTypeId()).properties();

        JSONObject json = new JSONObject();
        // datatbles的表头
        JSONArray columns = new JSONArray();
        // datatables的数据
        JSONArray datas = new JSONArray();
        JSONArray props = new JSONArray();
        for (int i = 0; i < propList.size(); i++) {
            Property property = propList.get(i);
            if (property.getDataTypeId().intValue() == 4 && property.getFormat() != null) {
                props.add(property.getName());
                String format = property.getFormat();
                String[] formatArray = format.split("[|]");
                JSONArray col = new JSONArray();
                for (int r = 0; r < formatArray.length; r++) {
                    String colValue = formatArray[r];
                    col.add(colValue);
                }
                columns.add(col);
                PropValueBean valueBean = cache.getValueBean(resId.longValue(), property.getId().longValue());
                if (valueBean != null) {
                    String[] values = valueBean.getValue().split("<#>");
                    JSONArray row = new JSONArray();
                    for (int v = 0; v < values.length; v++) {
                        String[] dataArray = values[v].split("<@>");
                        JSONArray column = new JSONArray();
                        for (int d = 0; d < dataArray.length; d++) {
                            column.add(dataArray[d]);
                        }
                        row.add(column);
                    }
                    datas.add(row);
                }
            }
        }

        json.element("size", columns.size());
        json.element("columns", columns);
        json.element("data", datas);
        json.element("props", props);
        Struts2Utils.renderJson(json.toString());
        return null;
    }

    /**
     * 进入我的视图-实时性能 页面
     * 
     * @return
     */
    public String performance() {
        Long resTypeId = Long.parseLong(Struts2Utils.getParameter("id"));
        Long pId = Long.parseLong(Struts2Utils.getParameter("pId"));
        Struts2Utils.setRequestAttribute("id", resTypeId);
        Struts2Utils.setRequestAttribute("pId", pId);
        return "performance";
    }

    /**
     * 构建资源分类 实时性能动态列
     * 
     * @return
     */
    public String aoColumns() {
        JSONObject json = new JSONObject();
        try {
            Long resTypeId = Long.parseLong(Struts2Utils.getParameter("id"));
            CollectTaskService collectTaskService = SpringContextHolder.getBean(CollectTaskService.class);
            List<CollectTask> typelist = collectTaskService.findByResTypeId(resTypeId);
            List<CollectTask> parentCollectTask = collectTaskService.findByChildResTypeId(resTypeId);
            if (typelist != null) {
                if (parentCollectTask != null) {
                    typelist.addAll(parentCollectTask);
                }
            } else {
                typelist = parentCollectTask;
            }
            CollectFieldCache collectFieldCache = SpringContextHolder.getBean(CollectFieldCache.class);
            Set<Long> propSet = new HashSet<Long>();

            if (typelist == null) {
                json.element("size", "0");
            } else {
                for (CollectTask task : typelist) {
                    List<CollectField> fields = collectFieldCache.get(task.getId());
                    if (fields != null) {
                        for (CollectField field : fields) {
                            propSet.add(field.getProp());
                        }
                    }
                }
                List<Property> propertys = ResTypeBean.get(resTypeId).properties();
                for (int i = propertys.size() - 1; i >= 0; i--) {
                    Property prop = propertys.get(i);
                    if (!propSet.contains(prop.getId()) || prop.getDataTypeId() == 4) {
                        propertys.remove(i);
                    }
                }
                Collections.sort(propertys, new Comparator<Property>() {
                    @Override
                    public int compare(Property p0, Property p1) {
                        return p0.getDisplay().intValue() - p1.getDisplay().intValue();
                    }
                });
                json.element("size", propertys.size());
                json.element("data", propertys);

            }
            Struts2Utils.renderJson(json.toString());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e);
        }
        return null;
    }

    /**
     * 资源实时性能
     * 
     * @return
     */
    public String resPerformances() {
        JSONObject json = new JSONObject();
        JSONArray array = new JSONArray();
        Long resTypeId = Long.parseLong(Struts2Utils.getParameter("resTypeId"));
        CollectTaskService collectTaskService = SpringContextHolder.getBean(CollectTaskService.class);
        List<CollectTask> typelist = collectTaskService.findByResTypeId(resTypeId);
        List<CollectTask> parentCollectTask = collectTaskService.findByChildResTypeId(resTypeId);
        if (typelist != null) {
            if (parentCollectTask != null) {
                typelist.addAll(parentCollectTask);
            }
        } else {
            typelist = parentCollectTask;
        }
        CollectFieldCache collectFieldCache = SpringContextHolder.getBean(CollectFieldCache.class);

        try {
            Set<Long> propSet = new HashSet<Long>();
            for (CollectTask task : typelist) {
                List<CollectField> fields = collectFieldCache.get(task.getId());
                if (fields != null) {
                    for (CollectField field : fields) {
                        propSet.add(field.getProp());
                    }
                }
            }
            List<Property> propertys = ResTypeBean.get(resTypeId).properties();
            for (int i = propertys.size() - 1; i >= 0; i--) {
                Property prop = propertys.get(i);
                if (!propSet.contains(prop.getId()) || prop.getDataTypeId() == 4) {
                    propertys.remove(i);
                }
            }
            Collections.sort(propertys, new Comparator<Property>() {
                @Override
                public int compare(Property p0, Property p1) {
                    return p0.getDisplay().intValue() - p1.getDisplay().intValue();
                }
            });

            // init data
            Long pId = Long.parseLong(Struts2Utils.getParameter("pId"));
            ResBean[] childBeans = ResBean.get(pId).childrenByType(resTypeId);
            RealTimeService realTimeService = SpringContextHolder.getBean(RealTimeService.class);
            Long[] resIds = new Long[childBeans.length];
            for (int i = 0; i < childBeans.length; i++) {
                resIds[i] = childBeans[i].res().getId();
            }
            realTimeService.collectPropertyValues(resIds);
            PropertyValueCache cache = SpringContextHolder.getBean(PropertyValueCache.class);
            for (int i = 0; i < childBeans.length; i++) {
                Res res = childBeans[i].res();
                JSONObject entity = new JSONObject();
                entity.element("resName", res.getName());
                Date max = null;
                for (int r = 0; r < propertys.size(); r++) {
                    Property property = propertys.get(r);
                    if (property.getDataTypeId().intValue() == 4 && property.getFormat() != null) {
                        continue;
                    }
                    PropValueBean bean = cache.getValueBean(res.getId().longValue(), property.getId().longValue());
                    if (property.getDataTypeId().intValue() == DataTypeConstants.DATA_TYPE_BOOLEAN) {
                        if (DataTypeConstants.BOOLEAN_VALUE_TRUE.equals(bean.getValue())) {
                            entity.element("name" + r + "", DataTypeConstants.BOOLEAN_VALUE_TRUE_DISPLAY);
                        } else if (DataTypeConstants.BOOLEAN_VALUE_FALSE.equals(bean.getValue())) {
                            entity.element("name" + r + "", DataTypeConstants.BOOLEAN_VALUE_FALSE_DISPLAY);
                        } else {
                            entity.element("name" + r + "", bean == null ? "-" : bean.getValue());
                        }
                    } else {
                        entity.element("name" + r + "", bean == null ? "-" : bean.getValue());
                    }
                    if (max == null && bean != null) {
                        max = bean.getTime();
                    }
                    if (bean != null && bean.getTime().getTime() > max.getTime()) {
                        max = bean.getTime();
                    }
                    if (r == propertys.size() - 1) {
                        SimpleDateFormat ff = new SimpleDateFormat("HH:mm:ss yyyy-MM-dd");
                        entity.element("collectTime", max == null ? "-" : ff.format(max));
                    }
                }
                array.add(entity);
            }
            json.element("aaData", array);
            json.element("iTotalRecords", 0);
            json.element("iTotalDisplayRecords", 0);
            Struts2Utils.renderText(json.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void prepareModel() throws Exception {

    }

    @Override
    public String save() throws Exception {
        return null;
    }

    @Override
    public Object getModel() {
        return null;
    }

    @SuppressWarnings("rawtypes")
    class ResHealthSort implements Comparator {
        @Override
        public int compare(Object obj1, Object obj2) {
            ResBean res1 = (ResBean) obj1;
            ResBean res2 = (ResBean) obj2;
            if (res1.res().getHealthDegree() > res2.res().getHealthDegree()) {
                return 1;
            } else {
                return 0;
            }
        }
    }

}